/**
 * Created on 2007-03-08 23:52
 */
package game.input;

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import main.Main;
import manager.Manager;

/**
 * @author David Wallin
 * 
 * Input manager deals with keyboard input
 */
public class InputManager extends Manager implements KeyListener
{
	public static final InputManager		INSTANCE = new InputManager();
	
	private boolean							m_LowerLeftReleased;
	private boolean							m_LowerRightReleased;
	private boolean							m_MiddleLeftReleased;
	private boolean							m_MiddleRightReleased;
	private boolean							m_UpperLeftReleased;
	private boolean							m_UpperRightReleased;
	private boolean							m_MiddleRotateReleased;
	private boolean							m_LowerDropDownReleased;
	private boolean							m_QuitReleased;
	private boolean							m_PauseReleased;
	
	private int								m_LowerLeftKeyCode;
	private int								m_LowerRightKeyCode;
	private int								m_MiddleLeftKeyCode;
	private int								m_MiddleRightKeyCode;
	private int								m_UpperLeftKeyCode;
	private int								m_UpperRightKeyCode;
	private int								m_MiddleRotateKeyCode;
	private int								m_LowerDropDownKeyCode;
	private int								m_QuitKeyCode;
	private int								m_PauseKeyCode;
	
	private Control							m_LowerControl;
	private Control							m_MiddleControl;
	private Control							m_UpperControl;
	private Control							m_PreviewControl;
	
	private Main							m_MainWindow;
	
	private boolean							m_HighscoreAdded;
	private boolean							m_HasHighscoreAddedResult;
	private boolean							m_GameEndedThroughQuitPressed;
	
	/**
	 * @param lowerLeftKeyCode the KeyCode of the LowerLeft keyboard control to set
	 */
	public void setLowerLeftKeyCode(int lowerLeftKeyCode)
	{
		m_LowerLeftKeyCode = lowerLeftKeyCode;
	}
	
	/**
	 * @param lowerRightKeyCode the KeyCode of the LowerRight keyboard control to set
	 */
	public void setLowerRightKeyCode(int lowerRightKeyCode)
	{
		m_LowerRightKeyCode = lowerRightKeyCode;
	}

	/**
	 * @param middleLeftKeyCode the KeyCode of the MiddleLeft keyboard control to set
	 */
	public void setMiddleLeftKeyCode(int middleLeftKeyCode)
	{
		m_MiddleLeftKeyCode = middleLeftKeyCode;
	}
	
	/**
	 * @param middleRightKeyCode the KeyCode of the MiddleRight keyboard control to set
	 */
	public void setMiddleRightKeyCode(int middleRightKeyCode)
	{
		m_MiddleRightKeyCode = middleRightKeyCode;
	}
	
	/**
	 * @param upperLeftKeyCode the KeyCode of the UpperLeft keyboard control to set
	 */
	public void setUpperLeftKeyCode(int upperLeftKeyCode)
	{
		m_UpperLeftKeyCode = upperLeftKeyCode;
	}
	
	/**
	 * @param upperRightKeyCode the KeyCode of the UpperRight keyboard control to set
	 */
	public void setUpperRightKeyCode(int upperRightKeyCode)
	{
		m_UpperRightKeyCode = upperRightKeyCode;
	}
	
	/**
	 * @param middleRotateKeyCode the KeyCode of the MiddleRotate keyboard control to set
	 */
	public void setMiddleRotateKeyCode(int middleRotateKeyCode)
	{
		m_MiddleRotateKeyCode = middleRotateKeyCode;
	}
	
	/**
	 * @param lowerDropDownKeyCode the KeyCode of the LowerDropDown keyboard control to set
	 */
	public void setLowerDropDownKeyCode(int lowerDropDownKeyCode)
	{
		m_LowerDropDownKeyCode = lowerDropDownKeyCode;
	}
	
	/**
	 * @param pauseKeyCode the KeyCode of the Pause keyboard control to set
	 */
	public void setPauseKeyCode(int pauseKeyCode)
	{
		m_PauseKeyCode = pauseKeyCode;
	}

	/**
	 * @param quitKeyCode the KeyCode of the Quit keyboard control to set
	 */
	public void setQuitKeyCode(int quitKeyCode)
	{
		m_QuitKeyCode = quitKeyCode;
	}
	
	/**
	 * @param highscoreAdded the result of trying to add a highscore to set
	 */
	public void setHighscoreAdded(boolean highscoreAdded)
	{
		m_HasHighscoreAddedResult = true;
		m_HighscoreAdded = highscoreAdded;
	}
	
	/**
	 * Gets the current key code of the quit button
	 * 
	 * @return the m_QuitKeyCode
	 */
	public int getQuitKeyCode()
	{
		return m_QuitKeyCode;
	}
	
	/**
	 * @return the m_LowerLeftKeyCode
	 */
	public int getLowerLeftKeyCode()
	{
		return m_LowerLeftKeyCode;
	}
	
	/**
	 * @return the m_LowerRightKeyCode
	 */
	public int getLowerRightKeyCode()
	{
		return m_LowerRightKeyCode;
	}
	
	/**
	 * @return the m_MiddleLeftKeyCode
	 */
	public int getMiddleLeftKeyCode()
	{
		return m_MiddleLeftKeyCode;
	}
	
	/**
	 * @return the m_MiddleRightKeyCode
	 */
	public int getMiddleRightKeyCode()
	{
		return m_MiddleRightKeyCode;
	}
	
	/**
	 * @return the m_MiddleRotateKeyCode
	 */
	public int getMiddleRotateKeyCode()
	{
		return m_MiddleRotateKeyCode;
	}
	
	/**
	 * @return the m_LowerDropDownKeyCode
	 */
	public int getLowerDropDownKeyCode()
	{
		return m_LowerDropDownKeyCode;
	}
	
	/**
	 * @return the m_PauseKeyCode
	 */
	public int getPauseKeyCode()
	{
		return m_PauseKeyCode;
	}
	
	/**
	 * @return the m_UpperLeftKeyCode
	 */
	public int getUpperLeftKeyCode()
	{
		return m_UpperLeftKeyCode;
	}
	
	/**
	 * @return the m_UpperRightKeyCode
	 */
	public int getUpperRightKeyCode()
	{
		return m_UpperRightKeyCode;
	}
	
	/**
	 * Gets the result of the latest atempt to add a highscore
	 * 
	 * @return the m_HighscoreAdded
	 */
	public boolean getHighscoreAdded()
	{
		m_HasHighscoreAddedResult = false;
		
		return m_HighscoreAdded;
	}
	
	/**
	 * Gets the state of atempts to adding highscores. If this is false, getHighscoreAdded() will
	 * not return a valid result
	 * 
	 * @return the state of attempts at adding hihgscores
	 */
	public boolean getHasHighscoreAddedResult()
	{
		return m_HasHighscoreAddedResult;
	}
	
	/**
	 * Gets whether or not the game was ended through pressing the quit button or not
	 * 
	 * @return whether or not the game ended by pressing quit
	 */
	public boolean getGameEndedThroughQuitPressed()
	{
		boolean endedThroughQuit = m_GameEndedThroughQuitPressed;
		m_GameEndedThroughQuitPressed = false;
		
		return endedThroughQuit;
	}
	
	/**
	 * Set the callback instance of the lower control
	 * 
	 * @param control reference to the control to call for lower control keypresses
	 */
	public void setLowerControl(Control control)
	{
		m_LowerControl = control;
	}
	
	/**
	 * Set the callback instance of the middle control
	 * 
	 * @param control reference to the control to call for middle control keypresses
	 */
	public void setMiddleControl(Control control)
	{
		m_MiddleControl = control;
	}
	
	/**
	 * Set the callback instance of the upper control
	 * 
	 * @param control reference to the control to call for upper control keypresses
	 */
	public void setUpperControl(Control control)
	{
		m_UpperControl = control;
	}
	
	/**
	 * Set the callback instance of the preview control
	 * 
	 * @param control reference to the control to call for preview control keypresses
	 */
	public void setPreviewControl(Control control)
	{
		m_PreviewControl = control;
	}
	
	/**
	 * Set the callback instance of the main window
	 * 
	 * @param main reference to the main window to call for quit and pause keypresses
	 */
	public void setMainWindow(Main main)
	{
		m_MainWindow = main;
	}
	
	/**
	 * Get the callback instance of the main window
	 * 
	 * @return reference to the main window to call for quit and pause keypresses
	 */
	public Main getMainWindow()
	{
		return m_MainWindow;
	}
	
	public void forceGameOver()
	{
		if(m_MainWindow != null)
		{
			m_MainWindow.pressQuit();
		}
	}
	
	public String getStringRepresentation(int keyCode)
	{
		String text = KeyEvent.getKeyText(keyCode);
		
		if(text.length() > 1)
		{
			if(text.toUpperCase().equals("UNKNOWN KEYCODE: 0X0"))
			{
				text = "NOT SET";
			}
			
			text = "<" + text.toUpperCase() + ">";
		}
		
		return text;
	}
	
	/* (non-Javadoc)
	 * @see java.awt.event.KeyListener#keyPressed(java.awt.event.KeyEvent)
	 */
	public void keyPressed(KeyEvent key)
	{
		if((key.getKeyCode() == m_LowerLeftKeyCode) && m_LowerLeftReleased)
		{
			m_LowerLeftReleased = false;
			
			if(m_LowerControl != null)
			{
				m_LowerControl.pressLeft();
			}
		}
		
		if((key.getKeyCode() == m_LowerRightKeyCode) && m_LowerRightReleased)
		{
			m_LowerRightReleased = false;
			
			if(m_LowerControl != null)
			{
				m_LowerControl.pressRight();
			}
		}
		
		if((key.getKeyCode() == m_MiddleLeftKeyCode) && m_MiddleLeftReleased)
		{
			m_MiddleLeftReleased = false;
			
			if(m_MiddleControl != null)
			{
				m_MiddleControl.pressLeft();
			}
		}
		
		if((key.getKeyCode() == m_MiddleRightKeyCode) && m_MiddleRightReleased)
		{
			m_MiddleRightReleased = false;
			
			if(m_MiddleControl != null)
			{
				m_MiddleControl.pressRight();
			}
		}
		
		if((key.getKeyCode() == m_UpperLeftKeyCode) && m_UpperLeftReleased)
		{
			m_UpperLeftReleased = false;
			
			if(m_UpperControl != null)
			{
				m_UpperControl.pressLeft();
			}
		}
		
		if((key.getKeyCode() == m_UpperRightKeyCode) && m_UpperRightReleased)
		{
			m_UpperRightReleased = false;
			
			if(m_UpperControl != null)
			{
				m_UpperControl.pressRight();
			}
		}
		
		if((key.getKeyCode() == m_MiddleRotateKeyCode) && m_MiddleRotateReleased)
		{
			m_MiddleRotateReleased = false;
			
			if(m_MiddleControl != null)
			{
				m_MiddleControl.pressRotate();
				m_PreviewControl.pressRotate();
			}
		}
		
		if((key.getKeyCode() == m_LowerDropDownKeyCode) && m_LowerDropDownReleased)
		{
			m_LowerDropDownReleased = false;
			
			if(m_LowerControl != null)
			{
				m_LowerControl.pressDropDown();
			}
		}
		
		if((key.getKeyCode() == m_QuitKeyCode) && m_QuitReleased)
		{
			System.out.println("quit pressed");
			//m_QuitReleased = false;
			m_GameEndedThroughQuitPressed = true;
			
			if(m_MainWindow != null)
			{
				m_MainWindow.pressQuit();
			}
		}
		
		if((key.getKeyCode() == m_PauseKeyCode) && m_PauseReleased)
		{
			m_PauseReleased = false;
			
			if(m_MainWindow != null)
			{
				m_MainWindow.pressPause();
			}
		}
	}
	
	/* (non-Javadoc)
	 * @see java.awt.event.KeyListener#keyReleased(java.awt.event.KeyEvent)
	 */
	public void keyReleased(KeyEvent key)
	{
		m_LowerLeftReleased |= (key.getKeyCode() == m_LowerLeftKeyCode);
		m_LowerRightReleased |= (key.getKeyCode() == m_LowerRightKeyCode);
		m_MiddleLeftReleased |= (key.getKeyCode() == m_MiddleLeftKeyCode);
		m_MiddleRightReleased |= (key.getKeyCode() == m_MiddleRightKeyCode);
		m_UpperLeftReleased |= (key.getKeyCode() == m_UpperLeftKeyCode);
		m_UpperRightReleased |= (key.getKeyCode() == m_UpperRightKeyCode);
		m_MiddleRotateReleased |= (key.getKeyCode() == m_MiddleRotateKeyCode);
		m_LowerDropDownReleased |= (key.getKeyCode() == m_LowerDropDownKeyCode);
		m_QuitReleased |= (key.getKeyCode() == m_QuitKeyCode);
		m_PauseReleased |= (key.getKeyCode() == m_PauseKeyCode);
	}
	
	/* (non-Javadoc)
	 * @see java.awt.event.KeyListener#keyTyped(java.awt.event.KeyEvent)
	 */
	public void keyTyped(KeyEvent arg0)
	{
	}
	
	/**
	 * Constructor, initializes members
	 * Set to private to implement the Singleton design pattern
	 */
	private InputManager()
	{
		m_LowerLeftKeyCode = KeyEvent.VK_V;
		m_LowerRightKeyCode = KeyEvent.VK_B;
		m_MiddleLeftKeyCode = KeyEvent.VK_F;
		m_MiddleRightKeyCode = KeyEvent.VK_H;
		m_UpperLeftKeyCode = KeyEvent.VK_R;
		m_UpperRightKeyCode = KeyEvent.VK_U;
		m_MiddleRotateKeyCode = KeyEvent.VK_SPACE;
		m_LowerDropDownKeyCode = KeyEvent.VK_G;
		
		m_QuitKeyCode = KeyEvent.VK_ESCAPE;
		m_PauseKeyCode = KeyEvent.VK_ENTER;
		
		m_LowerLeftReleased = true;
		m_LowerRightReleased = true;
		m_MiddleLeftReleased = true;
		m_MiddleRightReleased = true;
		m_UpperLeftReleased = true;
		m_UpperRightReleased = true;
		m_MiddleRotateReleased = true;
		m_LowerDropDownReleased = true;
		m_QuitReleased = true;
		m_PauseReleased = true;
		
		m_LowerControl = null;
		m_MiddleControl = null;
		m_UpperControl = null;
		m_PreviewControl = null;
		
		m_HighscoreAdded = false;
		m_HasHighscoreAddedResult = false;
		m_GameEndedThroughQuitPressed = false;
	}
}
